package com.example.test_1_31_interceptor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Test131InterceptorApplication {

    public static void main(String[] args) {
        SpringApplication.run(Test131InterceptorApplication.class, args);

        // **** 拦截器的源码介绍 ****
        // 拦截器 分两步:
        // 1) 定义拦截器
        // 要实现: HandlerInterceptor 接口
        // 这是固定写法
        //

        // 2) 注册配置拦截器
        // 要实现 WebMvcConfigurer 接口
        // 这是一个MVC的一个配置器, 也可以配置一些别的内容, 不仅仅是配置拦截器

        //.addPathPatterns("/**") // /** 表示给所有方法都添加拦截器
        //.excludePathPatterns("/user/login")// 这个方法表示不拦截谁




        // *** DispatcherServlet 源码分析 ***

        // 源码跟踪技巧：
        //在阅读框架源码的时候, ⼀定要抓住关键点, 找到核⼼流程.
        //切忌从头到尾⼀⾏⼀⾏代码去看, ⼀个⽅法的去研究, ⼀定要找到关键流程, 抓住关键点, 先在宏观上
        //对整个流程或者整个原理有⼀个认识, 有精⼒再去研究其中的细节.

        //1. 首先观察启动日志

        //当Tomcat启动之后, 有⼀个核⼼的类DispatcherServlet, 它来控制程序的执⾏顺序.
        //所有请求都会先进到DispatcherServlet，执⾏doDispatch 调度⽅法. 如果有拦截器, 会先执⾏拦截器
        //preHandle() ⽅法的代码, 如果 preHandle() 返回true, 继续访问controller中的⽅法. controller
        //当中的⽅法执⾏完毕后，再回过来执⾏ postHandle() 和 afterCompletion() ，返回给DispatcherServlet,
        // 最终给浏览器响应数据

        // 2.初始化
        // DispatcherServlet的初始化⽅法 init() 在其⽗类 HttpServletBean 中实现的
        // 主要作⽤是加载 web.xml 中 DispatcherServlet 的 配置, 并调⽤⼦类的初始化

        // web.xml是web项⽬的配置⽂件，⼀般的web⼯程都会⽤到web.xml来配置，主要⽤来配置
        //Listener，Filter，Servlet等, Spring框架从3.1版本开始⽀持Servlet3.0, 并且从3.2版本开始通过配置
        //DispatcherServlet, 实现不再使⽤web.xml

        //在 HttpServletBean 的 init() 中调⽤了 initServletBean() , 它是在
        //FrameworkServlet 类中实现的, 主要作⽤是建⽴ WebApplicationContext 容器(有时也称上下⽂), 并
        // 加载 SpringMVC 配置⽂件中定义的 Bean到该容器中, 最后将该容器添加到 ServletContext 中.

        // 初始化web容器的过程中, 会通过onRefresh 来初始化SpringMVC的容器

        // 在initStrategies()中进⾏9⼤组件的初始化, 如果没有配置相应的组件，就使⽤默认定义的组件
        // ⽅法initMultipartResolver、initLocaleResolver、initThemeResolver、
        //initRequestToViewNameTranslator、initFlashMapManager的处理⽅式⼏乎都⼀样(1.2.3.7.8,9),从应
        //⽤⽂中取出指定的Bean, 如果没有, 就使⽤默认的.
        //⽅法initHandlerMappings、initHandlerAdapters、initHandlerExceptionResolvers的处理⽅式⼏乎都⼀样(4,5,6)

        //1. 初始化⽂件上传解析器MultipartResolver：从应⽤上下⽂中获取名称为multipartResolver的
        //Bean，如果没有名为multipartResolver的Bean，则没有提供上传⽂件的解析器
        //2. 初始化区域解析器LocaleResolver：从应⽤上下⽂中获取名称为localeResolver的Bean，如果没
        //有这个Bean，则默认使⽤AcceptHeaderLocaleResolver作为区域解析器
        //3. 初始化主题解析器ThemeResolver：从应⽤上下⽂中获取名称为themeResolver的Bean，如果
        //没有这个Bean，则默认使⽤FixedThemeResolver作为主题解析器
        //4. 初始化处理器映射器HandlerMappings：处理器映射器作⽤，1）通过处理器映射器找到对应的
        //处理器适配器，将请求交给适配器处理；2）缓存每个请求地址URL对应的位置（Controller.xxx
        //⽅法）；如果在ApplicationContext发现有HandlerMappings，则从ApplicationContext中获取
        //到所有的HandlerMappings，并进⾏排序；如果在ApplicationContext中没有发现有处理器映射
        // 器，则默认BeanNameUrlHandlerMapping作为处理器映射器

        // 5. 初始化处理器适配器HandlerAdapter：作⽤是通过调⽤具体的⽅法来处理具体的请求；如果在
        //ApplicationContext发现有handlerAdapter，则从ApplicationContext中获取到所有的
        //HandlerAdapter，并进⾏排序；如果在ApplicationContext中没有发现处理器适配器，则默认
        //SimpleControllerHandlerAdapter作为处理器适配器
        //6. 初始化异常处理器解析器HandlerExceptionResolver：如果在ApplicationContext发现有
        //handlerExceptionResolver，则从ApplicationContext中获取到所有的
        //HandlerExceptionResolver，并进⾏排序；如果在ApplicationContext中没有发现异常处理器解
        //析器，则不设置异常处理器
        //7. 初始化RequestToViewNameTranslator：其作⽤是从Request中获取viewName，从
        //ApplicationContext发现有viewNameTranslator的Bean，如果没有，则默认使⽤
        //DefaultRequestToViewNameTranslator
        //8. 初始化视图解析器ViewResolvers：先从ApplicationContext中获取名为viewResolver的Bean，
        //如果没有，则默认InternalResourceViewResolver作为视图解析器
        //9. 初始化FlashMapManager：其作⽤是⽤于检索和保存FlashMap（保存从⼀个URL重定向到另⼀
        //个URL时的参数信息），从ApplicationContext发现有flashMapManager的Bean，如果没有，则
        //默认使⽤DefaultFlashMapManager

        // *** 3 处理请求(核⼼) ***



        // **** 适配器模式 ****

        // 适配器模式定义
        //适配器模式, 也叫包装器模式. 将⼀个类的接⼝，转换成客⼾期望的另⼀个接⼝, 适配器让原本接⼝不兼
        //容的类可以合作⽆间.
        //简单来说就是⽬标类不能直接使⽤, 通过⼀个新类进⾏包装⼀下, 适配调⽤⽅使⽤. 把两个不兼容的接⼝
        //通过⼀定的⽅式使之兼容

        // 适配器模式⻆⾊
        //• Target: ⽬标接⼝ (可以是抽象类或接⼝), 客⼾希望直接⽤的接⼝
        //• Adaptee: 适配者, 但是与Target不兼容
        //• Adapter: 适配器类, 此模式的核⼼. 通过继承或者引⽤适配者的对象, 把适配者转为⽬标接⼝
        //• client: 需要使⽤适配器的对象
        //适配器模式的实现
        //场景: 前⾯学习的slf4j 就使⽤了适配器模式, slf4j提供了⼀系列打印⽇志的api, 底层调⽤的是log4j 或者
        //logback来打⽇志, 我们作为调⽤者, 只需要调⽤slf4j的api就⾏了.

        // ** 适配器模式的实现 **
        // 在 adaptor 包里面实现


        // 适配器模式应⽤场景
        //⼀般来说，适配器模式可以看作⼀种"补偿模式"，⽤来补救设计上的缺陷. 应⽤这种模式算是"⽆奈之
        //举", 如果在设计初期，我们就能协调规避接⼝不兼容的问题, 就不需要使⽤适配器模式了
        //所以适配器模式更多的应⽤场景主要是对正在运⾏的代码进⾏改造, 并且希望可以复⽤原有代码实现新
        //的功能. ⽐如版本升级等.


        // ****  统一格式返回  ****
        // 在 图书馆里系统中实现
        // 使用了泛型 在 Result


        // **** 统一异常处理 ****
        // 在 图书馆里系统中实现



    }

}
